POV-Ray : Newsgroups : povray.advanced-users : Question about scale & translation : Re: Question about scale & translation Server Time
28 Jul 2024 22:25:38 EDT (-0400)
  Re: Question about scale & translation  
From:
Date: 3 Aug 2003 18:28:55
Message: <3f2d8ca7$1@news.povray.org>
/*

Hi Steve!


                               --:--


Mirroring is very easy: make an union of the objects comprising the
first half of the stack, put this into the scene, then put its
mirror image into the scene:

    #declare HalfStack = union {
      // create the objects of the first half of the stack as shown
      // in my previous post (stacked vertically, i.e. in y-direction).
      }

    // put the HalfStack into the scene
    object { HalfStack }

    // grab the HalfStack (its y-range is 0 .. Position.y),  mirror it in
    // the xz-plane by inverting y (now the y-range is -Position.y .. 0),
    // then translate by (2*Position.y)*y (this is the same as
    // 2*Position*y) which gives an y-range of Position.y .. 2*Position.y,
    // i.e. the mirrored copy now is on top of the first HalfStack.
    object { HalfStack scale <1, -1, 1> translate 2*Position*y }


                               --:--


A different method would be to build the stack from the middle to both
ends by appending in the loop each object at both ends, i.e. after

    object { Object translate -MinY*y+Position }

insert

    object { Object translate -MinY*y+Position scale <1, -1, 1> }

Because now the double stack is partially below the checkered plane,
the plane{...}-statement must be replaced by

    plane { y, -Position.y pigment { checker scale 10 } }

and we need a new camera (greater distance; adjusted to the larger object):

    camera {
      location <1, 3, -2>*(Position.y-Start.y)
      look_at 0
      translate -Position+0.55*2*Position
      angle 30
      }

(The lower end now is (Start-Position), this replaces Start; then I've
simplified this new expression a bit.)
Of course the code would be more easily readable when Start were renamed
to Midpoint ...


                               --:--


Individual control of the stacked objects is possible by filling an array
with their individual scales/textures/lengths/... like

    #declare ScaleArray = array[Number] { 1, 2, 3, 3, 3, 2, 1 }
    #declare PigmentArray = array[Number] { P1, P1, P2, P2, P2, P1, P2 }

then using it in the loop:

    #declare Object = cylinder { 0, y, 1
      scale ScaleArray[Count]
      pigment { PigmentArray[Count] }
      finish { FinishArray[Count] }
      }

(assuming P1, P2, FinishArray are declared before this, and Number=6).


                               --:--


The multiplication by y in the translate modifier of the camera statement
is nonsense (in my previous post; corrected here): this multiplication
clears the x- and z-coordinate. There is no need to do that, but in this
special case it doesn't hurt, these coordinates are zero anyway.


                               --:--


Here comes a new example, illustrating a different and very flexible
approach -- again this whole mail is a POV-Ray-scene, I suggest to set
the following options and RUN!

// +SP8 +EP8 +W320 +H240 -F +D +A0.1

*/

// stacked cylinders, flexible control of scale

#declare Number = 40;
#declare Start = <0, 0, 0>; // arbitrary starting point

#declare Position = Start; // initialize position for object
#declare Scale = 18; // initialize scale factor for object

// loop for Counter = 0, 1, ..., Number-1
#declare Count = 0;
#while (Count<Number)

  // auxiliary variable,  ranging from 0 to 1
  #declare C_N = Count/(Number-1);

  // determine the scaling factor; in this example:
  //   begin with 1 (see above)
  //   in the first quarter (C_N<0.25): decrease by 1
  //   next quarter (C_N<0.50): stay constant
  //   third quarter (C_N<0.75): decrease by 0.5
  //   rest: scale by 0.4
  // Using Count instead of C_N also is possible, but when Number
  // changes, all #case values have to be adjusted accordingly.
  // (Adjusting the initial value for Scale and the Scale-changes
  // are also required; this could be automated, but is omitted here.)
  // My usage of the #switch statement is a bit unusual -- most
  // people would use #range-clauses. But I like it this way!
  #switch (true)
    #case (C_N<.25) #declare Scale = Scale-1;   #break
    #case (C_N<.50) /* don't change Scale */    #break
    #case (C_N<.75) #declare Scale = Scale-0.5; #break
    #else           #declare Scale = 1;
    #end//switch
  // it's not necessary to check for the lower bound (i.e. to use
  // #case (C_N>=.50 & C_N<0.75) instead of #case (C_N<0.75)
  // because the lower values are caught in the #case(s) above.
  //
  // +----------------------------------------------------------------+
  // ! Attention: C_N<0.5 means "first half of the NUMBER of objects  !
  // ! in the stack", NOT "first half of FINAL HEIGHT of stack"!      !
  // +----------------------------------------------------------------+

  // more #switch directives could determine/change other parameters:
  // Object, pigment, finish, rotation, ...

  // make next object to be stacked; may depend on Count
  #declare Object = cylinder { 0, y, 1
    // scale the object by Scale;
    // also try  scale <10, Scale, 10>  and  scale <Scale,10,Scale>
    scale Scale // calculated above
    // alternating colors; also try mod(Count,5)/4 etc.
    pigment { color rgb <1, mod(Count,2), 0.3> } // easy, isn't it?
    finish { ambient .4 diffuse .6 }
    }

  // find smallest and largest y of this object and its y-size
  #declare MinY = min_extent(Object).y;
  #declare MaxY = max_extent(Object).y;
  #declare SizeY= MaxY-MinY;

  // put object into scene with it's bottom at Position
  // (first translate the bottom to origin, from there to Position)
  object { Object translate -MinY*y + Position }
  //object { Object scale <1, -1, 1> translate +MinY*y - Position }

  // update the Position for the next object
  #declare Position = Position + SizeY*y;

  // loop
  #declare Count = Count+1;
  #end//while Count


// we all love this, even without reflecting sphere ...
plane { y, 0 pigment { checker scale 10 } }

// light
light_source { <-2, 3, -1>*1000, rgb 1 }

// camera, translated to look at 55% of the height of the stack of objects
camera {
  location <1, 3, -2>*(Position.y-Start.y)/2
  look_at 0
  translate Start+0.55*(Position-Start)
  angle 30
  }


// END


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.